package com.kamistoat.meimeistore.authserver.web;

import com.alibaba.fastjson.JSON;
import com.kamistoat.common.To.EsTo.RegisterUpTo;
import com.kamistoat.common.To.LoginSuccessTo;
import com.kamistoat.common.constant.AuthConstant;
import com.kamistoat.common.exception.BizCodeEnum;
import com.kamistoat.common.utils.R;
import com.kamistoat.meimeistore.authserver.vo.UserRegisterVo;
import com.kamistoat.meimeistore.authserver.feign.MemberFeignService;
import com.kamistoat.meimeistore.authserver.feign.SearchFeignService;
import com.kamistoat.meimeistore.authserver.feign.ThirdFeignService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import javax.validation.Valid;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

@Controller
public class IndexController {

    // 以后都用SpringMVC来映射简单页面
    /**
     * 访问 /login.html 访问登录页
     *
     * @return 页面的名字，用于跳转页面
     */
    @GetMapping("/login.html")
    public String loginPage(HttpSession session) {
        // 检查redis中是否已经存在名为loginUser的session
        Object attribute = session.getAttribute(AuthConstant.LOGINUSER_KEY);
        if(attribute==null) {
            return "login";  // 会自动加上thymeleaf:prefix和thymeleaf:suffix配置的前后缀
        }else{
            // 已经登陆过，直接跳到首页
            return "redirect:http://meimeistore.com";
        }
    }
//
//    /**
//     * 访问 /register.html 访问登录页
//     *
//     * @param model SpringMVC的库类，用于动态渲染页面
//     * @return 页面的名字，用于跳转页面
//     */
//    @GetMapping("/register.html")
//    public String registerPage(Model model) {
//        return "register";  // 会自动加上thymeleaf:prefix和thymeleaf:suffix配置的前后缀
//    }

    @Autowired
    ThirdFeignService thirdFeignService;
    @Autowired
    StringRedisTemplate stringRedisTemplate;
    @Autowired
    MemberFeignService memberFeignService;
    @Autowired
    SearchFeignService searchFeignServicel;

    /**
     * 当注册页面点击发送验证码时，页面并不会跳转，只是会向下面的路径发送带参数请求
     * 请求数据就是用户的手机号
     * 向redis中保存值，key就是 sms:code:手机号，值就是验证码_当前系统时间
     * 然后远程调用third模块中的短信发送接口
     *
     * @param phoneNum 用户手机号
     * @return R
     */
    @ResponseBody
    @GetMapping("/register/sendcode")
    public R sendCode(@RequestParam String phoneNum) {
        // 先看看redis中是否已经存在一个同手机号的验证码
        String oldCode = stringRedisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + phoneNum);
        if (!StringUtils.isEmpty(oldCode)) {
            // 如果已经存在，把这个验证码的时间拿出来
            Long oldTime = Long.parseLong(oldCode.split("_")[1]);
            if (System.currentTimeMillis() - oldTime < 60000) {
                // 如果是在60秒内重复发送验证码，就不准再发
                return R.error(BizCodeEnum.SMS_REPEAT_EXCEPTION.getCode(), BizCodeEnum.SMS_REPEAT_EXCEPTION.getMessage());
            }
        }
        // 生成验证码
        String code = UUID.randomUUID().toString().substring(0, 5);
        // redis存放值，key就是 sms:code:手机号，值就是验证码_当前系统时间
        stringRedisTemplate.opsForValue().set(
                AuthConstant.SMS_CODE_CACHE_PREFIX + phoneNum,
                code + "_" + System.currentTimeMillis(),
                AuthConstant.SMS_CODE_EXPIRE_TIME,
                AuthConstant.SMS_CODE_EXPIRE_UNIT);

        thirdFeignService.sendSMSCode_Register(
                phoneNum, code, AuthConstant.SMS_CODE_EXPIRE_TIME);
        return R.ok();
    }

    /**
     * 注册。点击注册后向数据库中保存用户信息，然后跳转回到登录页面。开启数据校验
     *
     * @param redirectAttributes 用于在重定向时传递数据
     * @return 直接重定向到登录页面
     */
    @PostMapping("/register")
    public String register(@Valid UserRegisterVo userRegisterVo, BindingResult result, RedirectAttributes redirectAttributes) {
        Map<String, String> errors = new HashMap<>();
        if (result.hasErrors()) {
            // 二次校验，首次校验在前端完成
            for (FieldError fieldError : result.getFieldErrors()) {
                String field = fieldError.getField();
                String defaultMessage = fieldError.getDefaultMessage();
                errors.put(field, defaultMessage);
            }
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.meimeistore.com/register.html";
        }

        R register = memberFeignService.register(userRegisterVo);
        if ((int) register.get("code") == 0) {
            // 远程接口调用成功
            // 删除redis中用过的验证码，并把姓名和手机号存到ES
            stringRedisTemplate.delete(AuthConstant.SMS_CODE_CACHE_PREFIX + userRegisterVo.getPhoneNum());
            RegisterUpTo registerUpTo = new RegisterUpTo();
            registerUpTo.setUsername(userRegisterVo.getUsername());
            registerUpTo.setPhoneNum(userRegisterVo.getPhoneNum());
            searchFeignServicel.registerUpToES(registerUpTo);
            return "redirect:http://auth.meimeistore.com/login.html";
        } else if (register.get("code").equals(15001)) {
            // 远程接口抛出手机号重复的异常
            errors.put("feignError", register.get("msg").toString());
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.meimeistore.com/register.html";
        } else {
            // 否则就是属于未知异常
            errors.put("feignError", "出现未知异常，请稍后再试");
            redirectAttributes.addFlashAttribute("errors", errors);
            return "redirect:http://auth.meimeistore.com/register.html";
        }
    }

    // 用于检验验证码是否正确
    @ResponseBody
    @GetMapping("/register/codeAuth")
    public Integer codeAuth(@RequestParam String phoneNum, @RequestParam String code) {
        String redisCode = stringRedisTemplate.opsForValue().get(AuthConstant.SMS_CODE_CACHE_PREFIX + phoneNum);
        if (StringUtils.isEmpty(redisCode)) {
            return 1;
        } else {
            redisCode = redisCode.split("_")[0];
            if (!redisCode.equals(code)) {
                return 2;
            } else {
                return 0;
            }
        }
    }

    // 前端检查用户名是否重复
    @ResponseBody
    @GetMapping("/register/usernameUnique")
    public Integer usernameUnique(@RequestParam String username) {
        Integer unique = searchFeignServicel.usernameUniqueES(username);
        return unique;
    }

    /**
     * 账号密码登录
     *
     * @param loginAccount 账号
     * @param password     密码
     * @return 重定向
     */
    @ResponseBody
    @GetMapping("/login")
    public Integer login(@RequestParam String loginAccount, @RequestParam String password, HttpSession session, HttpServletRequest request) {
        String IP = request.getHeader("X-Real-IP").split(",")[0];  // IP 地址
        String IPAddr = "未实现IP定位功能";  // IP定位
        R loginState = memberFeignService.login(loginAccount, password, IP, IPAddr);
        if ((int) loginState.get("code") == 0) {
            // 如果登录成功，就把注册信息保存到session中，并把session携带的message删除，防止干扰
            LoginSuccessTo loginSuccessTo = JSON.parseObject(loginState.get("data").toString(), LoginSuccessTo.class);
            session.setAttribute("message", null);
            session.setAttribute(AuthConstant.LOGINUSER_KEY, loginSuccessTo);
        }
        return (int) loginState.get("code");
    }

    /**
     * 登出
     * @param session 直接拦截发送的session，然后将其从Redis中删除
     * @return
     */
    @GetMapping("/loginout")
    public String loginout(HttpSession session){
        session.removeAttribute(AuthConstant.LOGINUSER_KEY);
//        String sessionId = session.getId();
//        stringRedisTemplate.delete(sessionId);
        return "login";
    }
}
